<?php

class Core {

    private $_profiler = null;

    private $_arg = null;

    private $_dispatcher = null;

    function __construct() {
        require CORE_PATH . 'Logs.php';
        require CORE_PATH . 'Env.php';
        require CORE_PATH . 'Autoload.php';
        require CORE_PATH . 'Arg.php';
        require CORE_PATH . 'Enum.php';
        if ( is_file( CORE_PATH . 'Runtime.php' ) ) {
            require CORE_PATH . 'Runtime.php';
        }
        
        require CORE_PATH . 'Json.php';
        require CORE_PATH . 'Param.php';
        require CORE_PATH . 'Request.php';
        require CORE_PATH . 'Response.php';
        
        require CORE_PATH . 'Dispatcher.php';
        
        if ( Env::Ins()->IsProfiler() ) {
            // Mem监视 & 使用性能分析器 CProfiler.
            require CORE_PATH . 'Profiler.php';
            $this->_profiler = new Profiler();
        }
        
        // 自动加载各种类
        spl_autoload_register( 'Autoload::Load' );
        
        // 获取自定义错误及异常
        register_shutdown_function( 'Core::FatalError' );
        set_exception_handler( 'Core::AppException' );
        
        $this->_arg = new Arg();
        $this->_dispatcher = new Dispatcher( $this->_arg );
    }

    function __destruct() {
        if ( Env::Ins()->IsProfiler() ) {
            // Mem监视 & 使用性能分析器 CProfiler.
            $this->_profiler->printMem();
            $this->_profiler->printTime( $this->_arg->get( Arg::PLAYER_ID ), $this->_arg->get( Arg::PROTO ) );
        }
    }

    function start() {
        Logs::Info( 'start' );
        
        // Env::Ins()->rereadConfig();
        Env::Ins()->isDevelop();
        
        // 获取客户端来的参数.
        // 检查参数合法性
        $this->_dispatcher->_checkArg();
        
        // 检查维护状态
        $this->_dispatcher->_checkMaintenance();
        
        // 检查客户端版本
        $this->_dispatcher->checkVersion();
        
        // 使用调度器 根据不同的portocal 转入不同的处理
        $this->_dispatcher->dispatch();
        
        // 处理完成，返回客户端
        $this->_dispatcher->response();
    }
    
    

    public static function FatalError() {
        if ( $e = error_get_last() ) {
            switch ( $e['type'] ) {
                case E_ERROR:
                case E_PARSE:
                case E_CORE_ERROR:
                case E_COMPILE_ERROR:
                case E_USER_ERROR:
                    ob_end_clean();
                    Logs::Halt( $e );
                    self::ResponseError( E_PROTO_RESULT::INVALID_DATA );
                    break;
            }
        }
    }

    public static function AppException( $e ) {
        $error = array();
        $error['message'] = $e->getMessage();
        $trace = $e->getTrace();
        if ( 'E' == $trace[0]['function'] ) {
            $error['file'] = $trace[0]['file'];
            $error['line'] = $trace[0]['line'];
        }
        else {
            $error['file'] = $e->getFile();
            $error['line'] = $e->getLine();
        }
        $error['trace'] = $e->getTraceAsString();
        Logs::Err( 'Exception:' . $error['message'] );
        Logs::Halt( $error );
        self::ResponseError( E_PROTO_RESULT::INVALID_DATA );
        
        // Exception::Catch();
    }

    // 发生错误或异常，结果返回客户端
    public static function ResponseError( $protoResult ) {
        $response = new Response();
        $response->PROTO_RESULT = $protoResult;
        $response->returnJson();
    
        exit;
    }
}